<template>
  <n-drawer v-model:show="showModal" :width="props.width" @update-show="handleUpdateShow">
    <n-drawer-content title="角色授权" closable>
      <n-flex vertical>
        <n-input v-model:value="permPattern" type="text" clearable placeholder="搜索" />
        <n-tree
          ref="permRef"
          class="n-perm-tree"
          block-line
          cascade
          checkable
          :show-irrelevant-nodes="false"
          :show-line="true"
          :pattern="permPattern"
          :data="dataList"
          :checked-keys="permCheckedKeys"
          :node-props="nodeProps"
          @update-checked-keys="handlePermCheckedKeysChange"
        />
      </n-flex>
      <template #footer>
        <n-space>
          <n-button v-if="hasPermission('bmpch:role:auth:save', '保存角色授权')" type="info" :loading="saveBtnLoading" @click="handleSave">
            <template #icon>
              <n-icon>
                <SaveOutlined />
              </n-icon>
            </template>
            保存
          </n-button>
        </n-space>
      </template>
    </n-drawer-content>
  </n-drawer>
</template>

<script lang="ts" setup>
import { h, ref, unref, watch } from 'vue';
import { NIcon, NSpace } from 'naive-ui';
import type { TreeInst, TreeOption } from 'naive-ui';
import { SaveOutlined } from '@vicons/antd';
import { Browser, HandFinger } from '@vicons/tabler';
import { usrPermQry } from '@yanfan/bmpch-tsapi/perm';
import { rolePermAdd001, rolePermQry002 } from '@yanfan/bmpch-tsapi/role';
import type * as BMPCH from '@yanfan/bmpch-tsapi/types';
import { usePermission } from '@yanfan/common/hooks';

defineOptions({
  name: 'BmpchRolePermAuth',
  titl: '角色授权',
});

const { hasPermission } = usePermission();

const props = withDefaults(
  defineProps<{
    show: boolean;
    width?: number;
    roleId: string | null;
  }>(),
  {
    show: false,
    width: 502,
  },
);

const emits = defineEmits<{
  (e: 'update:show', show: boolean): void;
  (e: 'refresh'): void;
}>();

const permRef = ref<TreeInst | null>(null);
const showModal = ref(false);
const saveBtnLoading = ref(false);

const dataList = ref<BMPCH.UsrPermQryOutput_PermDto[]>([]);
const permPattern = ref<string>('');
const permCheckedKeys = ref<Array<string>>([]);

watch(
  () => unref(props).show,
  (show) => {
    showModal.value = show;
    if (showModal.value) {
      usrPermQry({}).then((data) => {
        handleLeafNode(null, data.list);
        dataList.value = data.list;
      });
      loadRolePermData();
    } else {
      dataList.value = [];
      permCheckedKeys.value = [];
    }
  },
);

function handleSave() {
  const permCheckedData = permRef.value?.getCheckedData();
  const permIndeterminateData = permRef.value?.getIndeterminateData();
  const permList = new Array<BMPCH.RolePermAdd001Input_PermDto>();
  permCheckedData?.options.forEach((option) => {
    if (option && option.key != null) {
      permList.push({
        key: String(option.key),
        label: option.label || '',
        type: String(option.type ?? 'unknown'),
        halfFlg: 0,
      });
    }
  });
  permIndeterminateData?.options.forEach((option) => {
    if (option && option.key != null) {
      permList.push({
        key: String(option.key),
        label: option.label || '',
        type: String(option.type ?? 'unknown'),
        halfFlg: 1,
      });
    }
  });
  saveBtnLoading.value = true;
  rolePermAdd001({ roleId: props.roleId!, permList })
    .then(() => {
      handleUpdateShow(false);
      window.$message.success('保存成功');
    })
    .finally(() => (saveBtnLoading.value = false));
}

function handleLeafNode(parent: BMPCH.MenuPermQry002Output_PermDto | null, nodes: Array<any>) {
  nodes.map((node) => {
    node.parent = parent;
    if (node.type === 'view') {
      node.prefix = () =>
        h(
          NIcon,
          { size: 16 },
          {
            default: () => h(Browser),
          },
        );
    } else if (node.type === 'func') {
      node.prefix = () =>
        h(
          NIcon,
          { size: 16, color: '#4098fc' },
          {
            default: () => h(HandFinger),
          },
        );
    }
    if (node.children && node.children.length === 0) {
      node.isLeaf = true;
    } else {
      handleLeafNode(node, node.children);
    }
  });
}

function loadRolePermData() {
  rolePermQry002({ roleId: props.roleId! }).then((data) => {
    if (data.keys && data.keys.length > 0) {
      permCheckedKeys.value = data.keys;
    }
  });
}

function handleUpdateShow(show: boolean) {
  emits('update:show', show);
}

function handlePermCheckedKeysChange(keys: Array<string>) {
  permCheckedKeys.value = keys;
}

function nodeProps({ option }: { option: TreeOption }) {
  return {
    class: {
      'n-tree-node-label': true,
      'n-tree-node-label-view': option.type === 'view',
      'n-tree-node-label-func': option.type === 'func',
    },
  };
}
</script>

<style lang="scss" scoped>
:deep(.n-perm-tree) {
  .n-tree-node-label-func {
    .n-tree-node-content__text {
      color: #4098fc;
    }
  }
}
</style>
